TerraformでプライベートなRedshiftクラスターを作る
踏み台サーバーとは
踏み台サーバーはプライベートなサーバーにアクセスするために経由されるサーバーのことです。 今回はRedshiftクラスターはインターネットに接続していないため、EC2インスタンスを踏み台としてアクセスします。 こうすることで通信先を限定することができ、アクセスの管理がしやすくなります。 以下は今回の構成図です。
Redshiftクラスターにアクセスする場合は、EC2インスタンスを経由しなければアクセスできないようになっています。
Terraformでデプロイする
ネットワーク
resource "aws_vpc" "example" { cidr_block = "10.1.0.0/16" enable_dns_hostnames = true } resource "aws_internet_gateway" "example" { vpc_id = aws_vpc.example.id } resource "aws_subnet" "redshift_1a" { cidr_block = "10.1.1.0/24" availability_zone = "ap-northeast-1a" vpc_id = aws_vpc.example.id } resource "aws_subnet" "bastion" { cidr_block = "10.1.10.0/24" availability_zone = "ap-northeast-1a" vpc_id = aws_vpc.example.id } resource "aws_route_table" "main" { vpc_id = aws_vpc.example.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.example.id } } resource "aws_route_table_association" "bastion_main" { subnet_id = aws_subnet.bastion.id route_table_id = aws_route_table.main.id }
今回はサブネットを2つ作り、1つはRedshift用、1つを踏み台サーバー用(bastion)にしています。
インターネットゲートウェイを設置していますが踏み台サーバーのあるサブネットからしかアクセスできません。
ポイントとしてはVPCの設定でenable_dns_hostnames
をtrue
にしておくことです。
こうすることでVPC内からでもエンドポイントのドメイン名を解決できます。
Redshift
resource "aws_security_group" "redshift" { name = "redshift" vpc_id = aws_vpc.example.id description = "redshift cluster" ingress { from_port = 5439 to_port = 5439 protocol = "tcp" security_groups = [aws_security_group.bastion.id] } } resource "aws_redshift_cluster" "example" { cluster_identifier = "example-cluster" database_name = "example" master_username = "exampleuser" master_password = "SuperSecr3t" node_type = "dc2.large" cluster_type = "multi-node" number_of_nodes = 2 publicly_accessible = false cluster_subnet_group_name = aws_redshift_subnet_group.example.id vpc_security_group_ids = [aws_security_group.redshift.id] skip_final_snapshot = true } resource "aws_redshift_subnet_group" "example" { name = "example" subnet_ids = [aws_subnet.redshift_1a.id] }
Redshiftクラスターとそれ用のセキュリティグループの設定をしています。 ポイントとしては以下の通りです。
- セキュリティグループを設定しアクセス制御
- 踏み台サーバー用のセキュリティグループからのアクセスのみを許可
- マルチノード構成のためノード数を2以上に
publicly_accessible
で外部との通信を二重で拒否
注意点
- ポート番号は何も指定しないと
5439
になります。 - 検証用なので
skip_final_snapshot
はtrue
にしていますが、本番で使う場合は適宜設定してください。 - 簡略化のためにユーザー名とパスワードをコードに埋め込んでいますが、これは危険です。
- AWS Secrets Mangerなどを利用して安全に保管しましょう
EC2
resource "aws_security_group" "bastion" { name = "bastion" vpc_id = aws_vpc.example.id description = "bastion server" egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_instance" "bastion" { ami = "ami-0ca38c7440de1749a" # Amazon Linux 2 64_x86 instance_type = "t2.micro" subnet_id = aws_subnet.bastion.id iam_instance_profile = aws_iam_instance_profile.systems_manager.name associate_public_ip_address = true vpc_security_group_ids = [ aws_security_group.bastion.id ] }
今回は割愛しますが、EC2インスタンスへはSessionManager経由で接続します。 そのためのIAMロールは適宜設定してください。 ポイントとしては以下の通りです。
- 踏み台サーバー用のセキュリティグループを設定
- 今回はSessionManager経由なのでアウトバウンドの設定のみで十分
- 外部とのアクセス用にパブリックIPを割り当てる。
接続してみる
エンドポイントはマネージドコンソールかTerraformから確認することができます。 今回はTerraformから確認します。
$ terraform state show 'aws_redshift_cluster.example' | grep endpoint endpoint = "example-cluster.XXXXXX.ap-northeast-1.redshift.amazonaws.com:5439"
はじめにドメイン名が解決されているか確認してみます。
以下ではSession Managerで接続したEC2インスタンス内で作業を行なっていきます。
$ nslookup example-cluster.XXXXXX.ap-northeast-1.redshift.amazonaws.com Server: 10.1.0.2 Address: 10.1.0.2#53 Non-authoritative answer: Name: example-cluster.XXXXXX.ap-northeast-1.redshift.amazonaws.com Address: 10.1.1.214
IPアドレスの範囲的にクラスターはap-northeast-1a
にプロビジョニングされたようです。
マネージドコンソールから確認するとリーダーノード1つとコンピュートノード2つが作成されています。
リーダーノードのIPアドレスが返されています。
ここでパブリックIPが設定されいますが、これは外部からアクセス可能であるかにかかわらず表示されるものです。
パブリックおよびプライベートクラスターノードの IP アドレスは、クラスターがパブリックにアクセス可能であるかどうかに関係なく表示されます。
sh-4.2$ sudo yum install postgresql sh-4.2$ psql -h example-cluster.XXXXXX.ap-northeast-1.redshift.amazonaws.com -p 5439 -U exampleuser -d example Password for user exampleuser: psql (9.2.24, server 8.0.2) WARNING: psql version 9.2, server version 8.0. Some psql features might not work. SSL connection (cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256) Type "help" for help. example=# \l List of databases name | owner | encoding | access privileges --------------+-------------+----------+------------------- dev | rdsdb | UNICODE | example | exampleuser | UNICODE | padb_harvest | rdsdb | UNICODE | template0 | rdsdb | UNICODE | rdsdb=CT/rdsdb template1 | rdsdb | UNICODE | rdsdb=CT/rdsdb (5 rows)
無事に接続できました。 データベースも作成されています。
感想
Terraformを使用してプライベートなRedshiftクラスターを構築することができました。 VPCの設定も同時にできるので便利だと思います。 AdminerなどのWeb上で動くSQLクライアントを踏み台サーバーに設置すればHTTP経由でもアクセスできるので便利かもしれません。